package data;

import java.io.Serializable;
import java.util.Date;
import java.util.ListIterator;
import java.util.Vector;

/**
 * Data structure to hold Season data.
 * @author Jen
 *
 */
public class Season implements Serializable
{
	
	/**
	 * The serial number for Season
	 */
	private static final long serialVersionUID = 01;

	/** the episodes for this season */
	private Vector<Episode> episodes = new Vector<Episode>();
	
	/** The selected Episode to try download next */
	private Episode selectedEpisode = null;
	
	/** the number of the season */
	private int seasonNumber;
	
	/** This requires further planning as to how to populate the Episodes (from within this class/constructor?) */
	protected Season(int seasonNum) 
	{
		this.seasonNumber = seasonNum;
	}
	
	/**
	 * Add's current episode to this season, sorts it properly
	 * @param epNum The episode number.
	 * @param epTitle The episode title.
	 * @param torrentURL The torrent URL for the episode.
	 * @param description The description of the episode.
	 * @param airDate The airdate of the episode.
	 */
	protected void addEpisode(int epNum, String epTitle, String torrentURL, String description, Date airDate)
	{
		Episode newEpisode = new Episode(epNum, epTitle, torrentURL, description, airDate);
		//If the list is empty then just add
		if(episodes.isEmpty())
		{
			episodes.add(newEpisode);
		}
		//If the list is not empty, check to see if the last episode is presceeding the new episode
		else if (episodes.lastElement().getEpisodeNumber() < newEpisode.getEpisodeNumber())
		{
			episodes.add(newEpisode);
		}
		//Alas, just iterate and add when available.
		else
		{
			for(int i=0; i<episodes.size(); i++)
			{
				Episode e = episodes.get(i);
				
				if(e.getEpisodeNumber() > newEpisode.getEpisodeNumber())
				{
					episodes.add(i, newEpisode);
					break;
				}
			}
		}
		
		//New Episode is now selected.
		selectedEpisode = newEpisode;
	}
	
	/**
	 * Add's current episode to this season, sorts it properly
	 * @param newEpisode the new episode to add to this season.
	 */
	protected void addEpisode(Episode newEpisode)
	{
		//If the list is empty then just add
		if(episodes.isEmpty())
		{
			episodes.add(newEpisode);
		}
		//If the list is not empty, check to see if the last episode is presceeding the new episode
		else if (episodes.lastElement().getEpisodeNumber() < newEpisode.getEpisodeNumber())
		{
			episodes.add(newEpisode);
		}
		//Alas, just iterate and add when available.
		else
		{
			for(int i=0; i<episodes.size(); i++)
			{
				Episode e = episodes.get(i);
				
				if(e.getEpisodeNumber() > newEpisode.getEpisodeNumber())
				{
					episodes.add(i, newEpisode);
					break;
				}
			}
		}
		
		//New Episode is now selected.
		selectedEpisode = newEpisode;
	}
	
	/**
	 * Returns the season number.
	 * @return
	 */
	public int getSeasonNumber()
	{
		return this.seasonNumber;
	}
	
	/**
	 * Returns a string representation of the episode.
	 * @return String representation of the episode.
	 */
	public String toString()
	{
		String returnString = "";
		for(Episode e : episodes)
		{
			if(e == this.getSelectedEpisode())
			{
				returnString += "*";
			}
			else
			{
				returnString += " ";
			}
			returnString += "Season: "+this.getSeasonNumber()+" "+e.toString()+"\n";
			
		}
		return returnString;
	}
	
	public boolean merge(Season bSeason)
	{
		boolean returnBool = false;
		Vector<Episode> bEpisodeList = bSeason.getEpisodes();
		for(Episode a: episodes)
		{
			for(Episode b: bEpisodeList)
			{
				if(a.getEpisodeNumber() == b.getEpisodeNumber())
				{
					if(a.merge(b));
					{
						returnBool = true;
					}
				}
			}
		}
		return returnBool;
	}
	
	/**
	 * setSelectedEpisode - 
	 * 
	 * will set the selected episode using the episode number given and give a boolean
	 * return value which indicates success/failure.  Boolean return type may not be necessary...
	 * 
	 * Special Number - (-1) - If -1 is sent in, selectedEpisode is null. 
	 * 
	 * @param episodeNumber - the episode number
	 * @return - the success/failure of the operation
	 */
	public boolean setSelectedEpisode(int episodeNumber)
	{
		boolean wasSet = false;

		if(episodeNumber == -1)
		{
			this.selectedEpisode = null;
		}
		else
		{
			for(Episode e : episodes)
			{
				if(e.getEpisodeNumber() == episodeNumber)
				{
					selectedEpisode = e;
					wasSet = true;
				}
			}
		}
		return wasSet;
	}
	
	/** 
	 * Sets the selected episode for the season based on the input
	 * 
	 * @param latestEpisode - 	If true, finds the latest episode in the season with torrents
	 * 							If false, finds the oldest episode in the season with torrents
	 * 
	 */
	public boolean setPreferedSelectedEpisode(boolean latestEpisode)
	{
		boolean returnBool = false;
		ListIterator<Episode> eIterator;
		if(latestEpisode)
		{
			eIterator = episodes.listIterator(episodes.size());
			while(eIterator.hasPrevious())
			{
				Episode e = eIterator.previous();
				if(e.getTorrentURL() != null && e.getTorrentURL().length() > 4 /*torrent url has to be atleast "http:// OR www."*/)
				{
					this.setSelectedEpisode(e.getEpisodeNumber());
					returnBool = true;
					break;
				}
			}
		}
		else
		{
			eIterator = episodes.listIterator();
			while(eIterator.hasNext())
			{
				Episode e = eIterator.next();
				String torrentURL = e.getTorrentURL();
				if(torrentURL != null && torrentURL.length() > 4 /*torrent url has to be atleast "http:// OR www."*/)
				{
					this.setSelectedEpisode(e.getEpisodeNumber());
					returnBool = true;
					break;
				}
			}
		}
		eIterator = null;
		return returnBool;
	}
	
	/**
	 * getSelectedEpisode - get the currently selected episode (the first if none was previously selected)
	 * @return - the selected episode
	 */
	public Episode getSelectedEpisode()
	{
		/*if (selectedEpisode == null)
		{
			selectedEpisode = episodes.firstElement();
		}
		*/
		return selectedEpisode;
	}
	
	/**
	 * goToNextEpisode - If there is a next episode, it will set the selectedEpisode to be it.
	 * @return true if there was a next episode, else false
	 */
	public boolean goToNextEpisode()
	{
		boolean returnBool = false;
		if(this.getSelectedEpisode() != null)
		{
			returnBool = this.setSelectedEpisode(this.getSelectedEpisode().getEpisodeNumber()+1);
		}
		return returnBool;
	}
	
  /////////////////////////
 //START EPISODE METHODS//
/////////////////////////
	
	protected int getEpisodeNumber()
	{
		return this.selectedEpisode.getEpisodeNumber();
	}		
	
	protected String getEpisodeTitle()
	{
		return this.selectedEpisode.getEpisodeTitle();
	}

	protected String getTorrentURL() 
	{
		return selectedEpisode.getTorrentURL();
	}

	protected String getDescription() 
	{
		return selectedEpisode.getDescription();
	}

	protected Date getAirDate() 
	{
		return selectedEpisode.getAirDate();
	}	
	
	public Vector<Episode> getEpisodes()
	{
		return episodes;
	}
	
	public Episode getEpisode(int episodeNum)
	{
		Episode returnEpisode = null;
		for(Episode e : this.episodes)
		{
			if(e.getEpisodeNumber() == episodeNum)
			{
				returnEpisode = e;
			}
		}
		return returnEpisode;
	}
	
  ///////////////////////
 //END EPISODE METHODS//
///////////////////////
}